package com.gwctv.controller.admin;

import com.gwctv.constant.JwtClaimsConstant;
import com.gwctv.dto.EmployeeDto;
import com.gwctv.dto.EmployeeLoginDTO;
import com.gwctv.dto.EmployeePageDTO;
import com.gwctv.entity.Employee;
import com.gwctv.properties.JwtProperties;
import com.gwctv.result.PageResult;
import com.gwctv.result.Result;
import com.gwctv.service.EmployeeService;
import com.gwctv.utils.JwtUtil;
import com.gwctv.vo.EmployeeLoginVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * controller层 接收登录请求响应数据
 * @Slf4j 将日志输出到控制台
 * @RestController 作用1：控制反转(将此类的bean对象交给IOC容器管理)
 * 作用2：底层封装@ResponceBody注解可以使响应给前端的数据为json格式
 * 作用3：将此类标识为控制器
 * @Tag 作用于类上(表示对类的说明)
 * RequestMapping 将公有请求地址写在类上@RequestMapping中
 */
@Slf4j
@RequestMapping("/admin/employee")
@RestController
@Tag(name = "员工控制类",description = "员工相关接口")
public class EmployeeController {

     // @Autowired 依赖自动注入(注入此接口实现类的bean对象)
    @Autowired
    private EmployeeService employeeService;

    // 自动注入jwt令牌属性配置类
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 接收登录请求响应数据
     * @param employeeLoginDTO 封装前端请求数据
     * @ResquestBody 将前端请求体数据封装在 employeeLoginDTO对象中
     * @PostMapping 限定前端请求方式为 post
     * @ApiResponse 描述API 的响应信息
     * @Operation 描述接口方法
     */
    @ApiResponse(responseCode = "200",description = "查询成功",content = @Content(schema = @Schema(implementation = Result.class)))
    @Operation(summary = "员工登录")
    @PostMapping("/login")
    public Result login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        // 校验登录是否成功
        Employee employee = employeeService.login(employeeLoginDTO);

        // 向jwt载荷中添加自定义信息
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        claims.put(JwtClaimsConstant.NAME, employee.getName());

        // 生成token(jwt令牌)
        String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);

        /**
         * 把响应给前端的数据封装在employeeLoginVO对象中
         * 使用builder()方法创建对象并对其属性赋值的前提是
         * EmployeeLoginVO类加有注解@Builder
         * 疑问：这里为什么不用给EmployeeLoginVO类上加@component注解，
         * 加了之后，我们在这里就不需要使用建造者模式了呀，使用@AutoWried
         * 自动注入不就可以了吗？
         * 答：原因1：EmployeeLoginVO类所在模块sky-pojo模块中没有引入springboot起步依赖
         *     原因2：
         */
        EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
                .id(employee.getId())
                .userName(employee.getUsername())
                .name(employee.getName())
                .token(token)
                .build();
        return Result.success(employeeLoginVO);
    }

    /**
     * 新增员工
     * @param employeeDto 接收前端参数
     * @return
     * @Postmapping注解中为何不写路径？因为在类上已经使用注解标注
     */
    @ApiResponse(responseCode = "200",description = "新增员工成功时返回结果",content = @Content(schema = @Schema(implementation = Result.class)))
    @Operation(summary = "新增员工",description = "实现新增员工功能")
    @PostMapping
    public Result save(@RequestBody EmployeeDto employeeDto){
        log.info("新增员工:{}",employeeDto);
        // 调用业务逻辑层
        employeeService.save(employeeDto);
        return Result.success();
    }

    /**
     * 分页查询
     * @param employeePageDTO 接收前端请求参数
     * @return 返回result对象
     * GetMapping 限定前端发来的请求方式为get
     */
    @ApiResponse(responseCode = "200",description = "分页查询返回的结果",content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "404",description = "分页查询失败",content = @Content(schema = @Schema(implementation = Result.class)))
    @Operation(summary = "分页查询",description = "实现分页查询功能")
    @GetMapping("/page")
    public Result<PageResult> page(EmployeePageDTO employeePageDTO){
        log.info("员工分页查询的参数为:{}",employeePageDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageDTO);
        // 响应给前端Result对象，并将pageResult封装在其中
        return Result.success(pageResult);
    }

    /**
     * 修改员工账号状态
     * @param status 接收前端传入的状态路径参数
     * @param id 接收前端传入的地址栏查询参数
     * @return 返回成功信息
     * 注意1：路径参数使用@PathVariable注解标注
     * 注意2：员工id前端传入方式为query查询参数，不需要注解标注即可接收
     * 注意3：接收前端传入参数的变量名尽量和前端参数名保持一致，这样无须手工指定
     */
    @PostMapping("/status/{status}")
    public Result startOrStop(@PathVariable Integer status,Long id){
        log.info("启用禁用员工账号：{},{}",status,id);
        // 调用service层中的方法
        employeeService.startOrStop(status,id);
        return Result.success();
    }

    /**
     * 根据员工id查询员工信息
     * @param id 员工id
     * @return 给前端返回员工信息
     */
    @GetMapping("/{id}")
    public Result<Employee> getById(@PathVariable Long id){
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }

    /**
     * 根据前端传入数据修改员工信息
     * @param employeeDto 接收前端传入的数据
     * @return 返回成功数据
     * 注意：此处未写请求路径，因为请求路径已标注在类上
     */
    @PutMapping
    public Result update(@RequestBody EmployeeDto employeeDto){
        employeeService.update(employeeDto);
        return Result.success();
    }
}
















